﻿#define _CRT_SECURE_NO_WARNINGS
// ↑ 将本行在代码放在第一行可以避免 scanf的报错问题（仅在VS编译器里）

//【入门】5.类和对象(4)
//【入门】6.类和对象(5)（开头对上节课的收尾：date-date）

//【头文件包含】
//C++的主要头文件
#include<iostream>//c++的输入输出流
using std::cout, std::endl;

#include<map>
//C的主要头文件
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h> 




//【命名空间】


//【结构体声明】【类声明】
/*学习：基本的默认的成员函数*/class DatePra
{
public: 
	///*构造函数*/Date()
	//{
	//	_year =0;_month =1; _day =1;
	//}
	/*1.构造函数*/DatePra(int year=0, int month=1,int day=1)//（全缺省实现不带参调用）
	{
		_year = year;_month = month; _day = day;
		_save = (int*)malloc(sizeof(int) *3);
		_save[0] = _year;
		_save[1] = _month;
		_save[2] = _day;
	}
	/*2.拷贝构造*/DatePra(DatePra&d)//构造函数的另一种重载
	{
		_year =d._year;_month = d._month; _day = d._day;
		_save = (int*)malloc(sizeof(int) * 3);//开辟拷贝的动态内存空间
		memcpy(_save, d._save, sizeof(int) * 3);//深拷贝
	}
	void PrintDate()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
		cout <<"malloc " << _save << endl;
		cout <<"save=" << _save[0] << _save[1] << _save[2] << endl;
	}
	/*3.析构函数*/~DatePra()
	{
		if (_save!=nullptr)
		{
			free(_save);
			cout << "free " << _save << endl;
			_save = nullptr;
			_year = 0;_month = _day = 1;
		}
	}
	/*4.运算符重载函数 ==*/bool operator==(const DatePra& d)
	{
		return _year == d._year 
			&& _month == d._month 
			&& _day == d._day;
	}
	/*4.运算符重载函数 >*/bool operator>(const DatePra& d)
	{
		return (_year > d._year )||
			(_year >= d._year&& _month > d._month) ||
			(_year >= d._year && _month >= d._month && _day > d._day) ;
	}
	/*4.运算符重载函数 <*/bool operator<(const DatePra& d)
	{
		return (!operator>(d)) && (!operator==(d));
	}
	DatePra& operator=(const DatePra& d)
	{
		if(this!=&d)
		{ 
			_year = d._year; _month = d._month; _day = d._day;
			if (_save != nullptr)free(_save);
			cout << "free " << _save << endl;
			_save = (int*)malloc(sizeof(int) * 3);//开辟拷贝的动态内存空间
			memcpy(_save, d._save, sizeof(int) * 3);//深拷贝
		}
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
	int* _save;

};


/*实践：实现一个完善的日期类*/class Date
{
public:
	/*根据年月获取当月天数*/int GetMonthDay(int year, int month)
	{
		static int monthDays[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if (month == 2 && (year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
		{
			return 29;
		}
		return monthDays[month];
	}
	/*构造函数*/Date(int year = 0, int month = 1, int day = 1)
	{
		if (year >= 0 && month >= 1 && month <= 12 && day >= 1 && day <= GetMonthDay(year, month))
		{
			_year = year; _month = month; _day = day;
		}
		else cout << "date illegel" << endl;

	}
	/*拷贝构造*/Date(const Date& d)
	{
		_year = d._year; _month = d._month; _day = d._day;
	}
	/*打印日期*/void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	/*运算符重载*/
	bool operator<(const Date& d)
	{
		return (_year < d._year)
			|| (_year <= d._year && _month < d._month)
			|| (_year <= d._year && _month <= d._month && _day < d._day);
	}
	bool operator>(const Date& d)
	{
		return (_year > d._year)
			|| (_year >= d._year && _month > d._month)
			|| (_year >= d._year && _month >= d._month && _day > d._day);
	}
	bool operator==(const Date& d)
	{
		return !operator<(d) && !operator<(d);
	}
	bool operator<=(const Date& d)
	{
		//老师的写法
		//return *this <d||*this==d;
		return !(operator>(d));//return operator==(d) || operator<(d);
	}
	bool operator>=(const Date& d)
	{
		return !(operator<(d));
	}
	bool operator!=(const Date& d)
	{
		return !operator==(d);
	}

	Date& operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year; _month = d._month; _day = d._day;
		}
		return *this;
	}
	Date& operator+=(int day)
	{
		if (day < 0)return *this -= -day;
		_day += day;
		while (_day > GetMonthDay(_year, _month))
		{
			_day -= GetMonthDay(_year, _month);
			++_month;

			 if (_month == 13)
			 {
				 _month = 1;
				++ _year;
			 }
		}
		 return *this;
	}
	Date operator+(int day)//循环
	{
		Date ret(*this);
		/*ret._day += day;
		while (ret._day > GetMonthDay(ret._year, ret._month))
		{
			ret._day -= GetMonthDay(ret._year, ret._month);
			ret._month ++;

			if (ret._month == 13)
			{
				ret._month = 1;
				ret._year ++;
			}
		}*/
		ret += day;//复用+=
		return ret;

	}
	//Date& operator+=(int day)//递归实现(本来要写+号发现递归暂时不能避免元日期的改变索性变成+=)
	 //{
		// int monthd = GetMonthDay(_year, _month);
		// if (_day + day <= monthd)
		// {
		//	 _day += day;
		//	 return *this;
		// }
		// else
		// {
		//	 _month++;
		//	 if (_month == 13)
		//	 {
		//		 _year++;
		//		 _month = 1;
		//	 }
		//	 return operator+=(day - monthd);
		// }
	 //}
	 //下节课继续
	Date& operator-=(int day)
	{
		
		if (day < 0)return *this += -day;
		_day -= day;
		while (_day < 1)
		{
			_month--;
			if (_month == 0)
			{
				_month = 12;
				_year--;
			}
			_day += GetMonthDay(_year, _month);
		}
		return *this;
	}
	Date operator-(int day)
	{
		Date ret(*this);
	/*	ret._day -= day;
		while (ret._day < 1)
		{
			ret._month--;
			if (ret._month == 0)
			{
				ret._month = 12;
				ret._year--;
			}
			ret._day += GetMonthDay(ret._year, ret._month);
		}*/
		ret -= day;//复用-=
		return ret;
	}
	Date& operator++()//前置返回加之后的值
	{
		*this += 1;
		return *this;
	}
	Date operator++(int)//后置，返回加之前值 
	{
		Date tmp(*this);
		*this += 1;
		return tmp;
	}
	Date& operator--()
	{
		*this -= 1;
		return *this;
	}
	Date operator--(int)
	{
		Date tmp(*this);
		*this -= 1;
		return tmp;
	}
	int  operator-(Date& d)//老师的
	{
		int flag = 1;
		Date max =*this;
		Date min = d;
		if (*this < d) { max = d; min = *this; flag = -1; }
		int n = 0;
		while (min != max)
		{
			++n;
			++min;
		}
		return n*flag;
	}
	//int  operator-(Date& d)//我的
	//{
	//	int ret = 0;
	//	if (*this > d)
	//	{
	//		while ((d + ret) != *this)ret++;
	//		return ret;
	//	}
	//	else if (*this < d)
	//	{
	//		while ((*this + ret) != d)ret++;			
	//		return -ret;
	//	}
	//	return ret;
	//}

	/*析构函数*/~Date()
	{
		_year = 0; _month = _day = 1;
	}
private:
	int _year;
	int _month;
	int _day;
protected:

};

//【函数声明】
void Test1();void Test2();void Test3();

//【主函数】
int main()
{
	//Test1();
	Test2();
	//Test3();

	cout << "****主函数结束****" << endl;
	return 0;
}

//【函数定义】

/*测试用例*/void Test1()
{
	printf("****测试用例开始****\n");
	Date d1; d1.Print();
	Date d2(2024, 2, 23); d2.Print();
	Date d3(2025, 4, 23); d3.Print();
	//比较运算符
	cout << "d2<d3  :" << (d2 < d3) << endl;
	cout << "d2>d3  :" << (d2 > d3) << endl;
	cout << "d2=d3  :" << (d2 == d3) << endl;
	cout << "d2<=d3 :" << (d2 <= d3) << endl;
	cout << "d2>=d3 :" << (d2 >= d3) << endl;
	cout << "d2!=d3 :" << (d2 != d3) << endl;
	//加减运算符
	Date d4 = d2 + 10; d4.Print();
	Date d5 = d3 + 10; d5.Print();
	(d2 += 10) += 5; d2.Print();//在实现加等减等 等在原值上运算结果赋给原值的运算符重载返回值应该以引用的方式返回
	d4=d2 - 10; d4.Print();
	d2 -= 10; d2.Print();
	/*d3 - d2;*/
	int gap = d5 - d2;
	printf("%d\n", gap);
	printf("****测试用例结束****\n\n");
}



/*测试用例*/void Test2()
{
	printf("****测试用例开始****\n");
	DatePra d1;
	DatePra d2(2025, 3, 1);
	d1.PrintDate(); d2.PrintDate();
	d1 = d2; d1.PrintDate();
	
	printf("****测试用例结束****\n\n");
}

/*测试用例*/void Test3()
{
	printf("****测试用例开始****\n");
	
	printf("****测试用例结束****\n\n");
}

//【笔记】

//【入门】5.类和对象(4)
//六种默认成员函数：默认构造函数用户不定义，编译器会自动生成默认
	//【默认2“析构函数”】：对象声明周期结束时自动调用的函数，完成对象内的【资源清理】工作，并非对对象的销毁
	//【默认3“拷贝构造”】：类的示例化时，复制另一个对象  "类名 对象名（类名&被拷贝对象名）"
		//拷贝构造必须用引用、且不能重载|可以理解为构造函数的一种重载
		//【额外】传参可以理解为一种拷贝构造
		// 拷贝构造默认函数时将对象按一个字节一个字节实现浅拷贝
	//【默认4“运算符重载”】：增强程序可读性，是具有特殊函数名的函数，具有返回值、变量、函数名、参数列表
		//关键字 operator后面接重载运算符号 ：返回值类型 operator操作符(参数列表)
		//在成员函数中比较实际是“调用该运算符重载函数的对象”和“传递的被比较对象的引用”进行比较
		//能重载的必须是类类型，5个运算符不能重载（1..*  2.:: 3.sizeof 4.?: 5..）
		//= 的运算符重载函数和拷贝构造默认函数类似，将对象按一个字节一个字节实现浅拷贝
	//浅拷贝在日期类这种类可以满足使用，但是如果在类似栈这种需要开辟动态内存空间的类时
	// 浅拷贝会将拷贝对象的空间首地址指针会和被拷贝对象指向同一空间，在析构时发生二次释放，引发程序崩溃
	// 在开辟了动态空间的类拷贝和赋值时需要自行编写拷贝构造和赋值运算符重载函数实现深拷贝，重新开辟一块空间复制存放被拷贝空间的值



